package com.flyqiu.flow.bpmn.element;

import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.annotation.JSONField;
import com.flyqiu.common.tools.StringTools;
import com.flyqiu.flow.bpmn.FlyFlowElementConstants;
import com.flyqiu.flow.bpmn.base.ScriptModel;
import lombok.Data;
import lombok.EqualsAndHashCode;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@EqualsAndHashCode(callSuper = true)
@Data
public class SequenceFlow extends BaseProcElement {
    @JSONField(serialize = false, deserialize = false)
    private BaseProcElement targetNode;
    @JSONField(serialize = false, deserialize = false)
    private BaseProcElement sourceNode;

    private String targetDefKey;

    private String sourceDefKey;

    private String sequencesType;

    private List<ScriptModel> conditionalExpression;

    public void setTargetNode(BaseProcElement targetNode) {
        updateProcModel(this.targetNode, targetNode);
        this.targetNode = targetNode;
        this.targetDefKey = targetNode.getDefKey();
    }

    private void updateProcModel(BaseProcElement old, BaseProcElement newElement) {
        if (processModel == null || processModel.isLock()) return;
        List<BaseProcElement> elements = processModel.elements;
        Map<String, BaseProcElement> elementMap = processModel.elementMap;
        if (elements == null) {
            return;
        }
        if (old != null) {
            elements.remove(old);
            elementMap.remove(old.getDefKey());
        }

        if (newElement == null) return;
        elementMap.put(newElement.getDefKey(), newElement);
        elements.add(newElement);

    }

    public void setSourceNode(BaseProcElement sourceNode) {
        updateProcModel(this.sourceNode, sourceNode);
        this.sourceNode = sourceNode;
        this.sourceDefKey = sourceNode.getDefKey();
    }

    @Override
    public String getElementType() {
        return FlyFlowElementConstants.ELEMENT_TYPE_SEQUENCE_FLOW;
    }


    @Override
    protected void initElement(JSONObject element, ProcessModel processModel) {
        sourceDefKey = element.getString("sourceRef");
        targetDefKey = element.getString("targetRef");
        handlerConditionExpression(element);
    }

    private void handlerConditionExpression(JSONObject element) {
        if (!element.containsKey("conditionExpression")) {
            return;
        }
        JSONArray conditionExpressions = element.getJSONArray("conditionExpression");
        if (conditionExpressions == null || conditionExpressions.isEmpty()) {
            return;
        }
        conditionalExpression = new ArrayList<>();
        for (int i = 0; i < conditionExpressions.size(); i++) {
            JSONObject expressionsConfig = conditionExpressions.getJSONObject(i);
            ScriptModel script = handlerExpressionsConfig(expressionsConfig);
            if (script == null) continue;
            conditionalExpression.add(script);
        }
    }

    protected ScriptModel handlerExpressionsConfig(JSONObject expressionsConfig) {
        if (!expressionsConfig.containsKey("#conditionExpression")) {
            return null;
        }
        String expression = expressionsConfig.getString("#conditionExpression");
        ScriptModel script = new ScriptModel();
        script.setScriptExpression(expression);
        String scriptType = expressionsConfig.getString("scriptType");
        if (StringTools.isNotBlank(scriptType)) {
            script.setScriptType(scriptType);
        }
        return script;

    }

    @Override
    public String toString() {
        return String.format("{%s}----->{%s}", sourceDefKey, targetDefKey);
    }

}
